package com.lant.web.ao.impl;

import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import com.lant.enums.ResponseStatusEnum;
import com.lant.exception.ErrorMsgException;
import com.lant.pojo.LantResult;
import com.lant.utils.CodeUtil;
import com.lant.utils.DateUtil;
import com.lant.utils.ObjectUtils;
import com.lant.utils.RedisUtil;
import com.lant.utils.StringUtils;
import com.lant.web.ao.SMSVerifyAO;
import com.lant.web.constant.KEYConstant;

@Service("smsVerifyAO")
public class SMSVerifyAOImpl implements SMSVerifyAO {

    // 短信发送时长
    private static final Integer SMS_CODE_EXPIRE = 300;
    private static final String CODE_HAS_EXPIRED = "验证码已过期，请重新获取";
    private static final String CODE_ERROR = "验证码错误";
    private static final String UNKNOWN = "unknown";
    private static final Logger logger = LoggerFactory.getLogger(SMSVerifyAOImpl.class);

    /**
     * @Title: generateSMSVerificationCode
     * @Description: 生成短信验证码
     * @param: request
     * @param: Mobile
     * @author: YFL
     * @date: 2020年5月7日 上午9:07:09
     */
    @Override
    public LantResult generateSMSVerificationCode(HttpServletRequest request, String mobile) {
        if (ObjectUtils.isEmpty(mobile)) {
            return LantResult.build(ResponseStatusEnum.BAD_REQUEST.getValue(), "手机号码不能为空");
        }
        // 防止恶意刷接口
        this.checkRepeatSend(request, mobile);
        String code = CodeUtil.generateSixCode();
        logger.info("====手机号为：{}，新的短信验证码为：{}", mobile, code);
        // 将生成的随机字符串保存到redis中
        String key = String.format(KEYConstant.RANDOM_SMS_VERIFICATION_CODE_KEY, mobile);
        LantResult result = RedisUtil.set(key, code, SMS_CODE_EXPIRE);
        // 发送短信

        return result;
    }

    @Override
    public LantResult checkSMSVerify(String vercode, String mobile) {
        if (ObjectUtils.isEmpty(mobile)) {
            return LantResult.build(ResponseStatusEnum.BAD_REQUEST.getValue(), "手机号码不能为空");
        }

        if (ObjectUtils.isEmpty(vercode)) {
            return LantResult.build(ResponseStatusEnum.BAD_REQUEST.getValue(), "短信验证码不能为空");
        }

        // 组装KEY
        String key = String.format(KEYConstant.RANDOM_SMS_VERIFICATION_CODE_KEY, mobile);

        LantResult result = RedisUtil.get(key);

        Object data = result.getData();

        if (ObjectUtils.isNull(data)) {
            logger.error(CODE_HAS_EXPIRED);
            throw new ErrorMsgException(CODE_HAS_EXPIRED);
        }

        if (!vercode.equals(data)) {
            logger.error(CODE_ERROR);
            throw new ErrorMsgException(CODE_ERROR);
        }

        return LantResult.ok();
    }

    /**
     * @Title: getRemoteIpAddr
     * @Description: 获取远程IP地址
     * @param: request
     * @return: String
     * @author: YFL
     * @date: 2020年5月7日 下午7:30:16
     */
    private String getRemoteIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");

        if ((StringUtils.isTrimEmpty(ip)) || (UNKNOWN.equalsIgnoreCase(ip))) {
            ip = request.getHeader("Proxy-Client-IP");
        }

        if ((StringUtils.isTrimEmpty(ip)) || (UNKNOWN.equalsIgnoreCase(ip))) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }

        if ((StringUtils.isTrimEmpty(ip)) || (UNKNOWN.equalsIgnoreCase(ip))) {
            ip = request.getRemoteAddr();
        }

        if (!StringUtils.isTrimEmpty(ip)) {
            int i = ip.indexOf(',');

            if (i != -1) {
                ip = ip.substring(0, i);
            }
        }

        return ip;
    }

    /**
     * @Title: checkRepeatSend
     * @Description: 防止恶意刷接口
     * @param: request
     * @param: mobile
     * @return: boolean
     * @author: YFL
     * @date: 2020年5月7日 下午8:14:08
     */
    private boolean checkRepeatSend(HttpServletRequest request, String mobile) {
        // 后台判断发送短信次数验证IP和手机号
        int ipTime = 0;
        int mobileTime = 0;
        String remoteIpAddr = getRemoteIpAddr(request);
        String formatDate = DateUtil.formatDate(System.currentTimeMillis(), "yyyyMMdd");
        String ipKey = String.format(KEYConstant.IP_VERIFY_KEY, formatDate + "_" + remoteIpAddr);
        String mobileKey = String.format(KEYConstant.MOBILE_VERIFY_KEY, formatDate + "_" + mobile);

        LantResult ipResult = RedisUtil.get(ipKey);
        LantResult mobileResult = RedisUtil.get(mobileKey);

        String ipValue = (String) ipResult.getData();
        String mobileValue = (String) mobileResult.getData();

        if (ObjectUtils.isNull(ipResult.getData())) {
            ipValue = "0";
        } else {
            ipTime = Integer.parseInt(ipValue);
            ipTime++;
            ipValue = String.valueOf(ipTime);
        }

        if (ObjectUtils.isNull(mobileResult.getData())) {
            mobileValue = "0";
        } else {
            mobileTime = Integer.parseInt(mobileValue);
            mobileTime++;
            mobileValue = String.valueOf(mobileTime);
        }

        RedisUtil.set(ipKey, ipValue, 86400);
        RedisUtil.set(mobileKey, mobileValue, 86400);

        if (ipTime > 15 || mobileTime > 15) {
            return false;
        }

        return true;
    }
}
